﻿/*
 * @author: wizardc
 */

using System;
using System.Collections.Generic;
using SuperScrollView;
using UnityEngine;

namespace Dou.UI
{
    /// <summary>
    /// 超级循环列表
    /// 1. 支持不同尺寸不同样式的子 Item；
    /// 2. 支持直接设置数据源的方式来实现；
    /// </summary>
    public class SuperLoopDataList : LoopListView2
    {
        /// <summary>
        /// 根据数据索引获取渲染项名称
        /// </summary>
        public Func<int, string> getItemNameFunc;
        
        /// <summary>
        /// Item 创建时回调
        /// </summary>
        public event Action<GameObject, object, int> onItemInit;

        /// <summary>
        /// Item 生效时回调
        /// </summary>
        public event Action<GameObject, object, int> onItemEnable;
        
        /// <summary>
        /// Item 更新时回调
        /// </summary>
        public event Action<GameObject, object, int> onItemUpdate;
        
        /// <summary>
        /// Item 失效时回调
        /// </summary>
        public event Action<GameObject, int> onItemDisable;

        private readonly Dictionary<int, GameObject> _itemMap = new Dictionary<int, GameObject>();

        private ICollection _dataProvider;

        public ICollection dataProvider
        {
            set
            {
                if (_dataProvider != value)
                {
                    _dataProvider = value;
                    Refresh();
                }
            }
            get => _dataProvider;
        }
        
        protected override string GetItemNameByIndex(int index)
        {
            if (getItemNameFunc != null)
            {
                return getItemNameFunc(index);
            }
            return string.Empty;
        }

        protected override void OnInitItem(int index, GameObject gameObject)
        {
            onItemInit?.Invoke(gameObject, _dataProvider.GetItemAt(index), index);
        }

        protected override void OnAddItem(int index, GameObject gameObject)
        {
            _itemMap.Add(index, gameObject);
            var data = _dataProvider.GetItemAt(index);
            onItemEnable?.Invoke(gameObject, data, index);
            onItemUpdate?.Invoke(gameObject, data, index);
        }

        protected override void OnRemoveItem(int index, GameObject gameObject)
        {
            if (_itemMap.ContainsKey(index))
            {
                _itemMap.Remove(index);
                onItemDisable?.Invoke(gameObject, index);
            }
        }

        /// <summary>
        /// 数据源自身数据改变时，调用该方法对显示列表进行刷新
        /// </summary>
        public void Refresh()
        {
            if (GetCount() != _dataProvider.count)
            {
                SetCount(_dataProvider.count, false);
            }
            
            foreach (var kv in _itemMap)
            {
                var index = kv.Key;
                var go = kv.Value;
                onItemUpdate?.Invoke(go, _dataProvider.GetItemAt(index), index);
            }
        }

        /// <summary>
        /// 刷新指定 Item
        /// </summary>
        public void RefreshItem(int index)
        {
            if (_itemMap.TryGetValue(index, out var go))
            {
                onItemUpdate?.Invoke(go, _dataProvider.GetItemAt(index), index);
            }
        }

        /// <summary>
        /// 跳转到指定 Item 位置
        /// </summary>
        public void JumpToIndex(int index, float offset = 0)
        {
            MovePanelToItemIndex(index, offset);
        }

        /// <summary>
        /// 跳转到最开始
        /// </summary>
        public void JumpToTop(float offset = 0)
        {
            MovePanelToItemIndex(0, offset);
        }

        /// <summary>
        /// 跳转到最后
        /// </summary>
        public void JumpToBottom(float offset = 0)
        {
            MovePanelToItemIndex(_dataProvider.count - 1, offset);
        }
        
        /// <summary>
        /// 获取指定索引处的 Item, 可能为空
        /// </summary>
        public GameObject GetItemByIndex(int index)
        {
            if (_itemMap.ContainsKey(index))
            {
                return _itemMap[index];
            }
            return null;
        }
    }
}
